package com.xingda.packing.led;

import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.Charset;
import java.util.Objects;
import java.util.StringJoiner;

/**
 * 超过 1byte 长度的数据类型，低字节在前,高字节在后。
 * 
 * @author LEGION
 *
 */
public class LedHelper {

	/**
	 * 网络发送前缀
	 */
	private final static String prex = "ff ff ff ff ff ff 00 00 00 00";

	/**
	 * 包头一帧数据的起始
	 */
	private final static String start = "78";
	/**
	 * 协议版本
	 */
	private final static String ver = "34";
	/**
	 * 控制卡地址
	 */
	private final static String addr = "01 00";
	/**
	 * 通信命令 29字符串更新命令
	 */
	private final static String cmd = "29";
	/**
	 * 识别标志
	 */
	private final static String ident = "00 00 00 00";
	/**
	 * 帧计数
	 */
	private final static String frame = "00 00 00 00";
	/**
	 * 一帧结束标志
	 */
	private final static String end = "a5";

	/**
	 * 0=unicode编码 1=gb2312 编码
	 */
	private final static String content_code = "01";
	/**
	 * 0=保存数据模式 2=立即显示模式
	 */
	private final static String content_mode = "02";
	/**
	 * 字符串索引
	 */
	private final static String content_index = "00";
	/**
	 * 颜色1=红色 2=绿色 3=黄色 4=蓝色 5=紫色 6=青色 7=白色
	 */
	private final static String content_color = "03";

	/**
	 * int数字转byte字符串
	 */
	public static String lengthTOByteStr(int length) {
		String lengthByteStr = Integer.toHexString(length);
		int totalLength = 4;
		int byteStrLength = lengthByteStr.length();
		int padLength = totalLength - byteStrLength;
		StringBuilder padSB = new StringBuilder();
		for (int i = 0; i < padLength; i++) {
			padSB.append(0);
		}
		return padSB.append(lengthByteStr).toString();
	}

	/**
	 * byte字符串 高低位转换
	 */
	public static String changeHeightLow(String byteStr) {
		// 每次截取w字符
		int w = 2;
		int y = byteStr.length() / w;
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < y; i++) {
			int beginIndex = i * w;
			int endIndex = (i + 1) * w;
			sb.insert(0, byteStr.substring(beginIndex, endIndex));
			if (endIndex < byteStr.length()) {
				sb.insert(0, " ");
			}
		}
		return sb.toString();
	}

	/**
	 * 生成CRC校验码
	 */
	public static String getCRC(byte[] bytes) {
		int CRC = 0x0000ffff;
		int POLYNOMIAL = 0x0000a001;
		int i, j;
		for (i = 0; i < bytes.length; i++) {
			CRC ^= ((int) bytes[i] & 0x000000ff);
			for (j = 0; j < 8; j++) {
				if ((CRC & 0x00000001) != 0) {
					CRC >>= 1;
					CRC ^= POLYNOMIAL;
				} else {
					CRC >>= 1;
				}
			}
		}
		return Integer.toHexString(CRC);
	}

	/**
	 * 字符串byte转成byte数组
	 *
	 */
	public static byte[] getByte(String buffStr) {
		String[] a = buffStr.split("\\ ");
		byte[] aByte = new byte[a.length];
		for (int i = 0; i < a.length; i++) {
			aByte[i] = (byte) (0xff & Integer.parseInt(a[i], 16));
		}
		return aByte;
	}

	private static void write(byte[] bt, Socket socket) {
		try {
			if (Objects.isNull(socket)) {
				return;
			}
			OutputStream outputStream = socket.getOutputStream();
			outputStream.write(bt);
			socket.shutdownOutput();
			outputStream.close();
			socket.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 中文转十六进制字符串
	 */
	public static String zhToHex(String content) {
		String startString = "ffffff";
		StringJoiner sj = new StringJoiner(" ");
		byte[] bt = content.getBytes(Charset.forName("gb2312"));
		for (byte b : bt) {
			String hex = Integer.toHexString(b);
			hex = hex.startsWith(startString) ? hex.substring(hex.indexOf(startString) + startString.length())
					: "00 " + hex;
			sj.add(hex);
		}
		return sj.toString();
	}

	public static void send(String content, Socket socket) {
		String contentByte = zhToHex(content);
		int contentLength = contentByte.split("\\ ").length;
		// 内容byte字符串长度转成byte字符串
		String contentLengthByteStr = lengthTOByteStr(contentLength);
		// 高低位转换
		String contentChangeLneght = changeHeightLow(contentLengthByteStr);
		// 总内容长度=内容(的长度) + 内容长度(2)+ 颜色(1)+ 字符串索引(1)+显示方式(1)+编码(1)+2(01 00 暂未知什么意思)
		int dataLength = contentLength + 2 + 1 + 1 + 1 + 1 + 2;
		// 内容byte字符串长度转成byte字符串
		String datacontentLengthByteStr = lengthTOByteStr(dataLength);
		// 高低位转换
		String dataChangeLneght = changeHeightLow(datacontentLengthByteStr);
		StringJoiner dataByteSJ = new StringJoiner(" ");
		dataByteSJ.add(start).add(ver).add(addr).add(cmd).add(ident).add(frame).add(dataChangeLneght).add("01 00")
				.add(content_code).add(content_mode).add(content_index).add(content_color).add(contentChangeLneght)
				.add(contentByte);
		// 校验位
		String check = changeHeightLow(getCRC(getByte(dataByteSJ.toString())));
		dataByteSJ.add(check).add(end);
		byte[] bt = getByte(prex + " " + dataByteSJ);
		write(bt, socket);
	}
	public static void send(String content, Socket socket,String color) {
		String contentByte = zhToHex(content);
		int contentLength = contentByte.split("\\ ").length;
		// 内容byte字符串长度转成byte字符串
		String contentLengthByteStr = lengthTOByteStr(contentLength);
		// 高低位转换
		String contentChangeLneght = changeHeightLow(contentLengthByteStr);
		// 总内容长度=内容(的长度) + 内容长度(2)+ 颜色(1)+ 字符串索引(1)+显示方式(1)+编码(1)+2(01 00 暂未知什么意思)
		int dataLength = contentLength + 2 + 1 + 1 + 1 + 1 + 2;
		// 内容byte字符串长度转成byte字符串
		String datacontentLengthByteStr = lengthTOByteStr(dataLength);
		// 高低位转换
		String dataChangeLneght = changeHeightLow(datacontentLengthByteStr);
		StringJoiner dataByteSJ = new StringJoiner(" ");
		dataByteSJ.add(start).add(ver).add(addr).add(cmd).add(ident).add(frame).add(dataChangeLneght).add("01 00")
				.add(content_code).add(content_mode).add(content_index).add(color).add(contentChangeLneght)
				.add(contentByte);
		// 校验位
		String check = changeHeightLow(getCRC(getByte(dataByteSJ.toString())));
		dataByteSJ.add(check).add(end);
		byte[] bt = getByte(prex + " " + dataByteSJ);
		write(bt, socket);
	}

}
